#include "codeCounter.h"
#include "ui_codeCounter.h"

codeCounter::codeCounter(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::codeCounter)
{
    ui->setupUi(this);
    initForm();
    on_btnClear_clicked();
}

codeCounter::~codeCounter()
{
    delete ui;
}

void codeCounter::initForm()
{
    // 表头
    QStringList headText;
    headText << "文件名" << "类型" << "大小" << "总行数" << "代码行数" << "注释行数" << "空白行数" << "路径";

    // 表格样式
    int colCount = headText.count();
    ui->tableWidget->setColumnCount(colCount);
    ui->tableWidget->setHorizontalHeaderLabels(headText);
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setHighlightSections(false);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->verticalHeader()->setDefaultSectionSize(20);
    ui->tableWidget->verticalHeader()->setHighlightSections(false);

    // 设置列宽
    QList<int> colWidth;
    colWidth << 130 << 50 << 70 <<  80 << 70 << 70 << 70 << 150;
    for(int i = 0; i < colCount; ++i)
    {
        ui->tableWidget->setColumnWidth(i, colWidth[i]);
    }

    // 设置字体加粗
    QFont font;
    font.setBold(true);
    ui->txtRow->setFont(font);
    ui->txtSize->setFont(font);
    ui->txtCode->setFont(font);
    ui->txtNote->setFont(font);
    ui->txtFile->setFont(font);
    ui->txtFilter->setFont(font);
    ui->txtPath->setFont(font);
    ui->txtBlank->setFont(font);
    ui->txtCount->setFont(font);


}

bool codeCounter::checkFile(const QString& fileName)
{
    QFileInfo file(fileName);
    QString suffix = "*." + file.suffix();
    QString filter = ui->txtFilter->text().trimmed();

    QStringList filters = filter.split(" ");
    return filters.contains(suffix);
}

void codeCounter::codeCount(const QString& filePath)
{
    QDir dir(filePath);
    QFileInfoList fileInfos = dir.entryInfoList();
    foreach (QFileInfo fileInfo, fileInfos) {
        QString fileName = fileInfo.fileName();
        if (fileInfo.isFile()) {
            if (checkFile(fileName)) {
                _listFile << fileInfo.filePath();
            }
        } else {
            if (fileName == "." || fileName == "..") {
                continue;
            }

            //递归找出文件
            codeCount(fileInfo.absoluteFilePath());
        }
    }
}

void codeCounter::codeCount(const QString& fileName, int & lineCode, int& lineBlank, int& lineNotes)
{
    lineCode = lineBlank = lineNotes = 0;
    QFile file(fileName);
    // 两种注释方式: // 和 /**/
    if(file.open(QFile::ReadOnly))
    {
        QTextStream out(&file);
        QString line;
        while(!out.atEnd())
        {
            line = out.readLine();
            if(line.startsWith(" "))
            {
                line.remove(" ");
            }
            else if(line.startsWith("/*"))
            {
                lineNotes++;
            }
            else if(line.startsWith("//"))
            {
                lineNotes++;
            }
            else if(line.isEmpty())
            {
                lineBlank++;
            }
            else
            {
                lineCode++;
            }
        }
    }
}

void codeCounter::codeCount(const QStringList& files)
{
    int lineCode, lineBlank, lineNotes, count = files.count();
    on_btnClear_clicked();
    ui->tableWidget->setRowCount(count);

    quint32 totalLines = 0, totalBytes = 0, totalCodes = 0, totalNotes = 0, totalBlanks = 0;
    for(int i = 0; i < count; ++i)
    {
        QFileInfo fileInfo(files[i]);
        codeCount(fileInfo.filePath(), lineCode, lineBlank, lineNotes);
        int lineAll = lineCode + lineBlank + lineNotes;

        // 表格中格子对象
        QTableWidgetItem * itemName = new QTableWidgetItem;
        itemName->setText(fileInfo.fileName());
        QTableWidgetItem * itemSuffix = new QTableWidgetItem;
        itemSuffix->setText(fileInfo.suffix());
        QTableWidgetItem * itemSize = new QTableWidgetItem;
        itemSize->setText(QString::number(fileInfo.size()));
        QTableWidgetItem * itemLine = new QTableWidgetItem;
        itemLine->setText(QString::number(lineAll));
        QTableWidgetItem * itemCode = new QTableWidgetItem;
        itemCode->setText(QString::number(lineCode));
        QTableWidgetItem * itemNotes = new QTableWidgetItem;
        itemNotes->setText(QString::number(lineNotes));
        QTableWidgetItem * itemBlank = new QTableWidgetItem;
        itemBlank->setText(QString::number(lineBlank));
        QTableWidgetItem * itemPath = new QTableWidgetItem;
        itemPath->setText(fileInfo.filePath());

        // 对齐方式
        itemSuffix->setTextAlignment(Qt::AlignCenter);
        itemSize->setTextAlignment(Qt::AlignCenter);
        itemLine->setTextAlignment(Qt::AlignCenter);
        itemCode->setTextAlignment(Qt::AlignCenter);
        itemNotes->setTextAlignment(Qt::AlignCenter);
        itemBlank->setTextAlignment(Qt::AlignCenter);

        // 对格子对象对应到表格头部相关内容
        ui->tableWidget->setItem(i, 0, itemName);
        ui->tableWidget->setItem(i, 1, itemSuffix);
        ui->tableWidget->setItem(i, 2, itemSize);
        ui->tableWidget->setItem(i, 3, itemLine);
        ui->tableWidget->setItem(i, 4, itemCode);
        ui->tableWidget->setItem(i, 5, itemNotes);
        ui->tableWidget->setItem(i, 6, itemBlank);
        ui->tableWidget->setItem(i, 7, itemPath);

        totalBytes += fileInfo.size();
        totalCodes += lineCode;
        totalBlanks += lineBlank;
        totalLines += lineAll;
        totalNotes += lineNotes;

        if(i % 100 == 0)
        {
            qApp->processEvents();
        }
    }

    //统计结果
    _listFile.clear();
    ui->txtCount->setText(QString::number(count));
    ui->txtSize->setText(QString::number(totalBytes));
    ui->txtRow->setText(QString::number(totalLines));
    ui->txtCode->setText(QString::number(totalCodes));
    ui->txtNote->setText(QString::number(totalNotes));
    ui->txtBlank->setText(QString::number(totalBlanks));

    //计算百分比
    double percent = 0.0;
    //代码行所占百分比
    percent = ((double)totalCodes / totalLines) * 100;
    ui->labPercentCode->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //注释行所占百分比
    percent = ((double)totalNotes / totalLines) * 100;
    ui->labPercentNote->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
    //空行所占百分比
    percent = ((double)totalBlanks / totalLines) * 100;
    ui->labPercentBlank->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}

void codeCounter::on_btnOpenFile_clicked()
{
    qDebug() << "open file cliled\n";
    QString filter = QString("代码文件(%1)").arg(ui->txtFilter->text().trimmed());
    QStringList files = QFileDialog::getOpenFileNames(this, "选择文件", "./", filter);
    if(files.size() > 0)
    {
        ui->txtFile->setText(files.join("|"));
        codeCount(files);
    }
}

void codeCounter::on_btnClear_clicked()
{
    qDebug() << "clear clicked\n";
    ui->txtCount->setText("0");
    ui->txtSize->setText("0");
    ui->txtRow->setText("0");

    ui->txtCode->setText("0");
    ui->txtNote->setText("0");
    ui->txtBlank->setText("0");

    ui->labPercentCode->setText("0%");
    ui->labPercentNote->setText("0%");
    ui->labPercentBlank->setText("0%");
    ui->tableWidget->setRowCount(0);
}

void codeCounter::on_btnOpenDir_clicked()
{
    qDebug() << "open dir clicked\n";
    QString dir = QFileDialog::getExistingDirectory(this, "选择目录", "./", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (!dir.isEmpty()) {
        ui->txtPath->setText(dir);
        _listFile.clear();
        codeCount(dir);
        codeCount(_listFile);
    }
}
